<template>
    <div class="input-slider">
        <span v-text="name"></span>
        <div class="slider-warp" ref="slider">
            <span :style="{ width: 100 * percent + '%' }"><b @mousedown="mousedown($event)"
                   @touchstart="mousedown($event)"></b></span>
        </div>

        <!-- <input type="text" v-model="content" oninput="value=value.replace(/[^0-9.]/g,'')" /> -->

        <input type="text" ref="input" v-model="local" @input="onInput($event)" @focus="onInputFocus($event)"
               @blur="onInputBlur($event)" @change="onInputChange($event)" @keyup.enter="onInputEnter($event)" />
    </div>
</template>

<script>
export default {
    props: {
        value: { type: Number, required: true },
        step: { type: Number, required: false, default: 1 },
        min: { type: Number, required: false, default: 0 },
        max: { type: Number, required: false, default: 100 },
        unit: { type: String, required: false },
        name: { type: String, required: false },
        format: { type: Function, required: false },
        precision: { type: Number, required: false },
    },
    data () {
        return {
            slider: null,
            local: '',
        };
    },
    computed: {
        // 小数点位数
        decimal () {
            let step = "" + (this.step || "");
            let precision = this.precision;

            if (Number.isFinite(precision)) {
                return precision;
            } else if (!step) {
                return 0;
            } else if (!/\./.test(step)) {
                // 整数
                return 1;
            } else {
                let match = (step.match(/\.(\d*)/) || [])[1];
                let length = match ? match.length : 0;
                return length;
            }
        },
        localFormat () {
            return this.format ? this.format(this.getRange(this.local)) : this.getRange(this.local);
        },
        valueFormat () {
            return this.format ? this.format(this.getRange(this.value)) : this.getRange(this.value);
        },

        // 百分比
        percent: {
            get () {
                const length = this.max - this.min || 1;
                return Math.max(0, Math.min((100, this.valueFormat - this.min) / length));
            },
            set (value) {
                let length = this.max - this.min || 1;
                let content = value * length + this.min;
                let range = this.getRange(content)
                this.$emit("input", range);
            },
        },
    },

    watch: {
        value () {
            this.setContent()
        }
    },

    methods: {
        // 四舍五入取整
        mathRound (value, n) {
            let bei = Math.pow(10, n);
            let res = Math.round(value * bei) / bei;
            return +parseFloat(res.toPrecision(12));
        },
        getRange (val) {
            let value = this.mathRound(parseFloat(val) || 0, this.decimal);
            return Math.max(Math.min(this.max, value), this.min);
        },
        mousedown: function (event) {

            const touch = (event.targetTouches || [])[0];
            const clientX = touch ? touch.clientX : event.clientX;

            event.stopPropagation();
            event.preventDefault();

            this.slider = {
                width: this.$refs.slider.offsetWidth - 18,
                percent: this.percent,
                clientX: clientX,
            };

        },
        mousemove: function (event) {
            if (!this.slider) {
                return;
            }

            const touch = (event.targetTouches || [])[0];
            const clientX = touch ? touch.clientX : event.clientX;
            const offsetX = clientX - this.slider.clientX
            const percent = this.slider.percent + offsetX / this.slider.width;

            this.percent = Math.min(1, Math.max(0, percent));
            event.stopPropagation();
            event.preventDefault();
        },
        mouseup: function (e) {
            if (!this.slider) {
                return;
            }
            this.slider = null;
            e.stopPropagation();
            e.preventDefault();
        },

        // 修改输入框
        setContent () {
            if (this.localFormat != this.valueFormat) {
                this.local = this.valueFormat
            }
        },
        // 更新内容
        setValue () {
            if (this.localFormat != this.valueFormat) {
                this.$emit("input", this.localFormat);
                this.$emit("change", this.localFormat);
            }
        },

        onInputFocus (event) {
            this.lock = true;
            event.currentTarget.select();
        },
        onInputChange (event) {
            this.setValue()
        },
        onInputBlur (event) {
            this.lock = false;
            this.local = this.valueFormat
        },
        onInputEnter (event) {
            this.local = this.valueFormat
        },
        onInput (event) {
            this.setValue()
        }
    },
    mounted: function () {
        window.addEventListener("mousemove", this.mousemove, false);
        window.addEventListener("mouseup", this.mouseup, false);
        window.addEventListener("touchmove", this.mousemove, { passive: false });
        window.addEventListener("touchend", this.mouseup, { passive: false });
        this.local = this.valueFormat
    },
    beforeDestroy: function () {
        window.removeEventListener("mousemove", this.mousemove);
        window.removeEventListener("mouseup", this.mouseup);
        window.removeEventListener("touchmove", this.mousemove);
        window.removeEventListener("touchend", this.mouseup);
    },
};
</script>
<style lang="scss" scoped>
.input-slider {
    position: relative;
    display: flex;
    flex-direction: column;

    &>span {
        height: 14px;
        font-size: 12px;

        color: #666;
        line-height: 14px;
        text-align: left;
    }

    &>input {
        position: absolute;
        bottom: 0;
        right: 0;
        width: 48px;
        height: 32px;
        background: #ffffff;
        border-radius: 4px;
        border: 1px solid #e6e6e6;
        text-align: center;
        padding: 0;
        box-sizing: border-box;
        font-size: 14px;

        color: #000000;

        &:hover {
            border-color: #c7c7c7;
        }

        &:focus {
            border-color: #f6b2cd;
            box-shadow: 0 0 1px 1px #f6b2cd;
        }
    }
}

.slider-warp {
    position: relative;
    height: 32px;
    margin: 4px 64px 0 0;
    padding: 0 9px;

    &:before {
        content: '';
        position: absolute;
        height: 2px;
        left: 0;
        width: 100%;
        top: 50%;
        transform: translateY(-50%);
        background: #e8e8e8;
        border-radius: 4px;
    }

    span {
        display: inline-block;
        height: 100%;
        position: relative;

        &::before {
            content: '';
            position: absolute;
            left: -9px;
            top: 50%;
            right: 0;
            height: 4px;
            transform: translateY(-50%);
            background-color: #f9ccdd;
            border-radius: 2px;
        }

        b {
            position: absolute;
            top: 50%;
            right: 0;
            margin-right: -9px;
            width: 18px;
            height: 18px;
            transform: translateY(-50%);
            background: #ea4c89;
            border-radius: 9px;
            cursor: pointer;

            &::after {
                content: '';
                position: absolute;
                width: 4px;
                height: 4px;
                left: 50%;
                top: 50%;
                transform: translate(-50%, -50%);
                background-color: #fff;
                border-radius: 2px;
            }
        }
    }

    &:hover {
        &:before {
            background: #ddd;
        }

        span:before {
            background-color: #fab0cd;
        }

        span b {
            box-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
        }
    }
}
</style>
